using System;
using System.Collections;
using System.IO;
using System.Runtime.InteropServices;
using System.Web;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using Sedna.Core.Controller;
using Sedna.Core.Controls.Support;
using Sedna.Core.DataBinding;
using Sedna.Core.Tiles.Contents;
using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Shared;
using CrystalDecisions.Web;

namespace Sedna.Core.Controls
{
    public class CrystalReportViewer : WebControl, IContent, IConfigurationAware, IControlDataLoadAware
	{


		private string configurationId;
		private IConfiguration configuration;
		private CrystalDecisions.Web.CrystalReportViewer crystalReportViewer;
		private ReportDocument reportDocument;
		private HtmlInputHidden base64paramReports;
        private String contentPlaceHolderId;

        private IDataBinder binder;

		private bool isPrinting = false;
        private bool isExcelPrinting = false;


		public string ConfigurationId
		{
			get { return configurationId; }
			set { configurationId = value; }
		}

		public IConfiguration Configuration
		{
			get { return configuration; }
			set { configuration = value; }
		}
        
        public String ContentPlaceHolderId
        {
            get { return contentPlaceHolderId; }
            set { contentPlaceHolderId = value; }
        }

        #region Constructors
        
        public CrystalReportViewer()
        {
            crystalReportViewer = new CrystalDecisions.Web.CrystalReportViewer();
            crystalReportViewer.DisplayGroupTree = false;
            crystalReportViewer.HasToggleGroupTreeButton = false;
            crystalReportViewer.HasSearchButton = false;
            crystalReportViewer.HasDrillUpButton = false;
            crystalReportViewer.HasCrystalLogo = false;
            crystalReportViewer.HasPrintButton = false;
            crystalReportViewer.HasExportButton = false;
            crystalReportViewer.HasViewList = false;
            base64paramReports = new HtmlInputHidden();
            base64paramReports.ID = "reports_base64reportParams";
        }

        public CrystalReportViewer(IConfiguration configuration)
        {
            crystalReportViewer = new CrystalDecisions.Web.CrystalReportViewer();
            crystalReportViewer.DisplayGroupTree = false;
            crystalReportViewer.HasToggleGroupTreeButton = false;
            crystalReportViewer.HasSearchButton = false;
            crystalReportViewer.HasDrillUpButton = false;
            crystalReportViewer.HasCrystalLogo = false;
            crystalReportViewer.HasPrintButton = false;
            crystalReportViewer.HasExportButton = false;
            crystalReportViewer.HasViewList = false;
            base64paramReports = new HtmlInputHidden();
            base64paramReports.ID = "reports_base64reportParams";

            this.configuration = configuration as IConfiguration;
            this.ID = configuration.Id;
            this.configurationId = configuration.ObjectName;
        }
        #endregion

        protected override void OnInit(EventArgs e)
		{
			if(configuration == null)
			{
				configuration = (IConfiguration)SpringContextFactory.GetContext().GetObject(configurationId);
			}
			Controls.Add(crystalReportViewer);
			Controls.Add(base64paramReports);
            binder = new DataBinder(this, configuration, ExecutionContext.GetCurrent(ClientID));
			base.OnInit(e);
		}

		protected override void OnPreRender(EventArgs e)
		{
            Bind();
		}

		protected override void Render(System.Web.UI.HtmlTextWriter writer)
		{
			if(isPrinting)
			{
			    if (isExcelPrinting)
                    ExportExcelReportToResponse(Context.Response, reportDocument);
			    else
			        ExportPdfReportToResponse(Context.Response, reportDocument);
			}
			else
			{
				base.Render (writer);
			}
		}


		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);
			IExecutionContext executionContext = ExecutionContext.GetCurrent(ClientID);
			ControlUtil.ExecuteOnLoad(executionContext, Context, Configuration, this.ClientID);
		}

        protected override void OnUnload(EventArgs e)
        {
            base.OnUnload(e);

            if (reportDocument != null)
            {
                reportDocument.Close();   
                reportDocument.Dispose();
                reportDocument = null;
            }
        }

        public void OnDataLoad()
		{
			IExecutionContext executionContext = ExecutionContext.GetCurrent(ClientID);
			ControlUtil.ExecuteOnDataLoad(executionContext, Context, Configuration, this.ClientID);			
		}

	    protected virtual void Bind()
	    {
            object reportDocumentObj = null;
            object commandNameObj = null;
            object isAllPagesObj = null;
            object base64reportParamsObj = null;
            bool configIsOk = binder.GetPropertyValue("ReportDocument", out reportDocumentObj)
                                && binder.GetPropertyValue("CommandName", out commandNameObj)
                                && binder.GetPropertyValue("IsAllPages", out isAllPagesObj)
                                && binder.GetPropertyValue("Base64reportParams", out base64reportParamsObj);
	        
	        if (!configIsOk)
	        {
                throw new Exception("CrystalReportViewer is not configured properly. Some mandatory parameters are not set. Check configuration.");
	        }

            bool isAllPages = Convert.ToBoolean(isAllPagesObj);
            reportDocument = (ReportDocument)reportDocumentObj;
	        reportDocument.Refresh();
            crystalReportViewer.ReportSource = reportDocument;
            isPrinting = !"ShowReport".Equals(commandNameObj);
            isExcelPrinting = "PrintExcelReport".Equals(commandNameObj);
	        crystalReportViewer.DisplayToolbar = !isPrinting && !isAllPages;
            crystalReportViewer.SeparatePages = !isAllPages;
            base64paramReports.Value = (string)base64reportParamsObj;
	    }
	    
		private void ExportPdfReportToResponse(HttpResponse response, ReportDocument reportDocument)
		{
			response.Clear();
			byte[] buff = new byte[1024];
			int count = 0;
		    try
		    {
                Stream stream = reportDocument.ExportToStream(ExportFormatType.PortableDocFormat);

                response.ContentType = "application/pdf";
                //			response.AddHeader("Content-Type", "application/pdf");
                response.AddHeader("Content-Length", stream.Length.ToString());
                response.AddHeader("Content-Disposition", "inline;filename=form.pdf");

                while ((count = stream.Read(buff, 0, 1024)) > 0)
                {
                    response.OutputStream.Write(buff, 0, count);
                }
                response.Flush();
                response.Close();
		    }
		    catch(ParameterFieldCurrentValueException e)
		    {
                throw new SednaException(8001, e);
		    }
		}

        private void ExportExcelReportToResponse(HttpResponse response, ReportDocument reportDocument)
        {
            response.Clear();
            byte[] buff = new byte[1024];
            int count = 0;
            try
            {
                Stream stream = reportDocument.ExportToStream(ExportFormatType.Excel);

                response.ContentType = "application/vnd.ms-excel";
                response.AddHeader("Content-Length", stream.Length.ToString());
                response.AddHeader("Content-Disposition", "inline;filename=form.xls");

                while ((count = stream.Read(buff, 0, 1024)) > 0)
                {
                    response.OutputStream.Write(buff, 0, count);
                }
                response.Flush();
                response.Close();
            }
            catch (ParameterFieldCurrentValueException e)
            {
                throw new SednaException(8001, e);
            }
        }
    }
}
